

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;

public class Stringlist_TableWalker {

	private ArrayList<StringList> tokensList;
	private HashSet<CharClass> charClassValues;
	private HashSet<IdClass> idClassValues;
	private HashSet<Integer> endingStates;

	public Stringlist_TableWalker(String filename, String[][] table,
			HashSet<CharClass> charSet, HashSet<IdClass> idSet,
			HashSet<Integer> endingSet) {
		System.out.println();
		ArrayList<ArrayList<String>> dfa_table = new ArrayList<ArrayList<String>>();
		for (int row = 0; row < table.length; row++) {
			dfa_table.add(new ArrayList<String>());
			for (int col = 0; col < table[row].length; col++) {
				dfa_table.get(row).add(table[row][col]);
			}
		}

		final int NUM_STATES = dfa_table.size() - 1;
		final int NUM_TRANSITIONS = dfa_table.get(0).size() - 1;

		charClassValues = charSet;
		idClassValues = idSet;
		endingStates = endingSet;

		String currentToken = "";
		String currentState = dfa_table.get(1).get(0);

		int readChar = -2;
		Character currentChar = 32;
		Character prevChar = 32;
		String nextState = null;
		int columnIndex = 0;
		int currentRowIndex = -1;

		int begin = 0;
		int end = 0;
		int line = 1;

		tokensList = new ArrayList<StringList>();
		try {
			FileInputStream fstream = new FileInputStream(filename);
			DataInputStream dis = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new FileReader(filename));
			while (readChar != -1) {
				for (int i = 1; i <= NUM_STATES; i++) {
					if (dfa_table.get(i).get(0).equals(currentState)) {
						currentRowIndex = i;
						break;
					}
				}

				// IF CURRENT CHAR = '\t' || '\n' || CarriageReturn || ' ' THEN
				// READ NEXT CHAR
				if (prevChar == 9 || prevChar == 10 || prevChar == 13
						|| prevChar == 32) {
					readChar = br.read();
					currentChar = (char) readChar;
					end++;
					begin = end;
					if (prevChar == 10 || prevChar == 13) {
						begin = 0;
						end = 0;
						line++;
					}

				} else { // ELSE PUSH PREV INTO CURRENT
					currentChar = prevChar;
					prevChar = 32;
					end++;
				}

				// CHECK WITH DFA TABLE
				nextState = null;
				if ((columnIndex = dfa_table.get(0).indexOf(
						currentChar.toString())) != -1) {
					nextState = dfa_table.get(currentRowIndex).get(columnIndex);
				} else {
					for (int i = 1; i < dfa_table.get(0).size(); i++) {
						if (dfa_table.get(0).get(i) != null) {
							if (dfa_table.get(0).get(i).charAt(0) == '$') {
								for (CharClass chclass : charClassValues) {
									if (chclass.getName().equals(
											dfa_table.get(0).get(i))) {
										for (int charValue : chclass
												.getValidChars()) {
											if (currentChar == charValue) {
												nextState = dfa_table.get(
														currentRowIndex).get(i);
												break;
											}
										}
										if (nextState != null)
											break;
									}
								}
							}
						}
						if (nextState != null)
							break;
					}
				}

				// if next state isn't null, append character to token and
				// change state. Else check if valid state and place into
				// array list
				if (nextState != null) {
					currentToken += currentChar;
					currentState = nextState;
					prevChar = 32;
				} else {
					boolean stopLoop = false;
					for (Integer state : endingStates) {
						String[] states = dfa_table.get(currentRowIndex).get(0)
								.split(",");
						for (int j = 0; j < states.length; j++) {
							if (Integer.parseInt(states[j]) == state) {
								for (IdClass idClass : idClassValues) {
									for (Integer acceptState : idClass
											.getAcceptStates()) {
										for (int k = 0; k < states.length; k++) {
											if (Integer.parseInt(states[k]) == acceptState) {
												Data data = new Data(
														filename,
														Integer.toString(line),
														Integer.toString(begin),
														Integer.toString(end));
												ArrayList<Data> dataList = new ArrayList<Data>();
												dataList.add(data);
												StringList stringList = new StringList(
														dataList, currentToken);
												tokensList.add(stringList);
												end++;
												begin = end;
												stopLoop = true;
												break;
											}
										}
									}
									if (stopLoop)
										break;
								}
								if (stopLoop)
									break;
							}
						}
						if (stopLoop)
							break;
					}
					currentToken = "";
					prevChar = currentChar;
					currentState = dfa_table.get(1).get(0);
					end++;
					begin = end;
				}

			}

			dis.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public ArrayList<StringList> Stringlist_getTokensList() {
		return tokensList;
	}
}
